<?php
	/**
	 * Created by PhpStorm.
	 * User: mybook-lhp
	 * Date: 18/7/7
	 * Time: 下午11:19
	 */

	namespace app\common\exce;

	use app\common\utils\UtilEncryption;
	use think\App;
	use think\Db;
    use think\facade\Env;
    use think\Request;

	class Logger
	{

		protected $config = [
			'time_format' => ' c ',
			'single'      => false,
			'file_size'   => 2097152,

//			'path'        => \think\facade\Env::get('runtime_path') . 'log/',
			'apart_level' => [],
			'max_files'   => 0,
		];

		protected $writed = [];

		// 实例化并传入参数
		public function __construct($config = [])
		{
			if (is_array($config))
			{
				$this->config = array_merge($this->config, $config);
			}
		}


		/**
		 * 日志写入接口
		 * @access public
		 * @param array $params 日志信息
		 * @return bool
		 */
		public function save(array $params = [])
		{
			$logs = [];

			$i = 0;
			$url = request()->url(true);
			$sn = UtilEncryption::MakeSn();
			foreach ($params as $key => $param)
			{
				$logs[$i]['sn'] = $sn;
				$logs[$i]['url'] = $url;
				$logs[$i]['tage'] = $key;
				$logs[$i]['content'] = json_encode($param);
				$logs[$i]['create_time'] = time();
				$logs[$i]['update_time'] = time();
				$i ++;
			}

			Db::name('log_all')->insertAll($logs);
			$this->saveFile($params);
			return true;
		}


		/**
		 * 日志写入接口
		 * @access public
		 * @param array $log 日志信息
		 * @return bool
		 */
		public function saveFile(array $log = [])
		{
			if ($this->config['single'])
			{
				$destination = $this->config['path'] . 'single.log';
			} else
			{
				$cli = IS_CLI ? '_cli' : '';

				if ($this->config['max_files'])
				{
					$filename = date('Ymd') . $cli . '.log';
					$files = glob($this->config['path'] . '*.log');

					if (count($files) > $this->config['max_files'])
					{
						unlink($files[0]);
					}
				} else
				{
					$filename = date('Ym') . '/' . date('d') . $cli . '.log';
				}

				$destination = $this->config['path'] . $filename;
			}

			$path = dirname($destination);
			!is_dir($path) && mkdir($path, 0755, true);

			$info = '';
			foreach ($log as $type => $val)
			{
				$level = '';
				foreach ($val as $msg)
				{
					if (!is_string($msg))
					{
						$msg = var_export($msg, true);
					}
					$level .= '[ ' . $type . ' ] ' . $msg . "\r\n";
				}
				if (in_array($type, $this->config['apart_level']))
				{
					// 独立记录的日志级别
					if ($this->config['single'])
					{
						$filename = $path . DIRECTORY_SEPARATOR . $type . '.log';
					} elseif ($this->config['max_files'])
					{
						$filename = $path . DIRECTORY_SEPARATOR . date('Ymd') . '_' . $type . $cli . '.log';
					} else
					{
						$filename = $path . DIRECTORY_SEPARATOR . date('d') . '_' . $type . $cli . '.log';
					}
					$this->write($level, $filename, true);
				} else
				{
					$info .= $level;
				}
			}
			if ($info)
			{
				return $this->write($info, $destination);
			}
			return true;
		}

		protected function write($message, $destination, $apart = false)
		{
			//检测日志文件大小，超过配置大小则备份日志文件重新生成
			if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination))
			{
				try
				{
					rename($destination, dirname($destination) . DIRECTORY_SEPARATOR . time() . '-' . basename($destination));
				} catch (\Exception $e)
				{
				}
				$this->writed[$destination] = false;
			}

			if (empty($this->writed[$destination]) && !IS_CLI)
			{
				if (App::$debug && !$apart)
				{
					// 获取基本信息
					if (isset($_SERVER['HTTP_HOST']))
					{
						$current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
					} else
					{
						$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
					}

					$runtime = round(microtime(true) - App::getBeginTime(), 10);
					$reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞';
					$time_str = ' [运行时间：' . number_format($runtime, 6) . 's][吞吐率：' . $reqs . 'req/s]';
					$memory_use = number_format((memory_get_usage() - App::getBeginMem()) / 1024, 2);
					$memory_str = ' [内存消耗：' . $memory_use . 'kb]';
					$file_load = ' [文件加载：' . count(get_included_files()) . ']';

					$message = '[ info ] ' . $current_uri . $time_str . $memory_str . $file_load . "\r\n" . $message;
				}
				$now = date($this->config['time_format']);
				$ip = Request::instance()->ip();
				$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'CLI';
				$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
				$message = "---------------------------------------------------------------\r\n[{$now}] {$ip} {$method} {$uri}\r\n" . $message;

				$this->writed[$destination] = true;
			}

			if (IS_CLI)
			{
				$now = date($this->config['time_format']);
				$message = "[{$now}]" . $message;
			}

			return error_log($message, 3, $destination);
		}

	}